#include "myhead.h"

typedef struct node {
    int  fd;
    char ip[INET_ADDRSTRLEN];
    int  port;
    struct node *next;
} node_t;

static node_t *g_list = NULL;
static pthread_mutex_t g_list_mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_list_con = PTHREAD_COND_INITIALIZER;
int flag=0;

/* 线程安全地增删查 */
static void list_add(int fd, const char *ip, int port) {
    node_t *n = malloc(sizeof(node_t));
    n->fd = fd;
    strncpy(n->ip, ip, sizeof(n->ip));
    n->port = port;
    pthread_mutex_lock(&g_list_mtx);
    n->next = g_list;
    g_list = n;
    pthread_mutex_unlock(&g_list_mtx);
}

static void list_del(int fd) 
{
    pthread_mutex_lock(&g_list_mtx);
    node_t **pp = &g_list;
    while (*pp) {
        if ((*pp)->fd == fd) {
            node_t *tmp = *pp;
            *pp = tmp->next;
            free(tmp);
            break;
        }
        pp = &(*pp)->next;
    }
    flag=0;
    pthread_mutex_unlock(&g_list_mtx);
}

static node_t *list_find(int fd) {
    node_t *res = NULL;
    pthread_mutex_lock(&g_list_mtx);
    for (node_t *p = g_list; p; p = p->next)
        if (p->fd == fd) { res = p; break; }
    pthread_mutex_unlock(&g_list_mtx);
    return res;
}
// static void *tr_client(void *arg)
// {
//     while(1)
//     {
//         pthread_mutex_lock(&g_list_mtx);
//         node_t **pp = &g_list;
//         if((*pp)==NULL)
//         {
//             pthread_cond_wait(&g_list_con,&g_list_mtx);
//         }
//         printf("------服务器已经收到的用户有---------\n");
//         pp=&(*pp)->next;
//         while ((*pp)!=g_list&&flag == 1) {
//             printf("套接字：%d ,ip是%s ,端口是 %d\n",(*pp)->fd,(*pp)->ip,(*pp)->port);
//             pp = &(*pp)->next;
//         }
//         if( flag == 1 && (*pp)==g_list)
//         {
//             printf("套接字：%d ,ip是%s ,端口是 %d\n",(*pp)->fd,(*pp)->ip,(*pp)->port);
//         }
//         flag=0;
//         pthread_mutex_unlock(&g_list_mtx);
//         usleep(2000);
//     }
// }

/* --------------- 管理员线程 --------------- */
static void *admin_thread(void *arg) {
    while (1) {
        flag=1;
        printf("输入要说话的 fd（-1 刷新列表）：\n");
        int target;
        if (scanf("%d", &target) != 1) break;

        if (!list_find(target)) { printf("fd=%d 不在线\n", target); continue; }

        printf("输入要发送的内容：");
        char buf[50];
        if (scanf(" %49[^\n]", buf) != 1) continue;//[]是扫描集，只要括号内的

        if (send(target, buf, strlen(buf), 0) == -1)
            perror("send");
        else
            printf("已发送给 fd=%d\n", target);
    }
    return NULL;
}

/* --------------- 客户端线程 --------------- */
static void *client_thread(void *arg) {
    int fd = *(int *)arg;
    free(arg);

    /* 随时接收客户端数据（回显即可） */
    char buf[50];
    while (1) {
        ssize_t n = recv(fd, buf, sizeof(buf)-1, 0);
        if (n <= 0) break;
        buf[n] = 0;
        printf("[fd=%d 说] %s\n", fd, buf);
    }

    /* 下线 */
    close(fd);
    list_del(fd);
    printf("fd=%d 下线\n", fd);
    return NULL;
}

/* --------------- main --------------- */
int main() 
{
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if (listenfd == -1) { perror("socket"); exit(1); }

    int opt = 1;
    //设置端口取消绑定限制
    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in addr = {
        .sin_family = AF_INET,
        .sin_addr.s_addr = INADDR_ANY,
        .sin_port = htons(10000)
    };
    if (bind(listenfd, (struct sockaddr *)&addr, sizeof(addr)) == -1 ||
        listen(listenfd, 12) == -1) {
        perror("bind/listen"); exit(1);
    }

    /* 启动管理员线程 */
    pthread_t admin_tid;
    pthread_create(&admin_tid, NULL, admin_thread, NULL);
    pthread_detach(admin_tid);

    //搞一个线程重复刷新
    // pthread_t client_tid;
    // pthread_create(&client_tid, NULL, tr_client, NULL);
    // pthread_detach(client_tid);

    /* 主线程只负责 accept */
    while (1) {
        struct sockaddr_in caddr;
        socklen_t len = sizeof(caddr);
        int connfd = accept(listenfd, (struct sockaddr *)&caddr, &len);
        if (connfd == -1) { perror("accept"); continue; }

        char ip[INET_ADDRSTRLEN];
        //strcpy(ip,inet_ntoa(caddr.sin_addr));//只可以ipv4,不用
        inet_ntop(AF_INET, &caddr.sin_addr, ip, sizeof(ip));//inet_ntoa(struct in_addr in)
        int port = ntohs(caddr.sin_port);
        list_add(connfd, ip, port);
        //pthread_cond_signal(&g_list_con);
        flag = 1;
        printf("新连接 fd=%d %s:%d\n", connfd, ip, port);

        int *pfd = malloc(sizeof(int));
        *pfd = connfd;
        pthread_t tid;
        pthread_create(&tid, NULL, client_thread, pfd);
        pthread_detach(tid);
    }
    //循环内不要随便创建，考虑多个线程创造
    return 0;
}